import {
  Graph,
  Edge,
  Shape,
  NodeView
} from '@antv/x6'
class MyShape extends Shape.Rect {
  getInPorts() {
    return this.getPortsByGroup('in')
  }

  getOutPorts() {
    return this.getPortsByGroup('out')
  }

  getUsedInPorts(graph) {
    const incomingEdges = graph.getIncomingEdges(this) || []
    return incomingEdges.map((edge) => {
      const portId = edge.getTargetPortId()
      return this.getPort(portId)
    })
  }

  getNewInPorts(length) {
    return Array.from({
        length,
      },
      () => {
        return {
          group: 'in',
        }
      },
    )
  }

  updateInPorts(graph) {
    const minNumberOfPorts = 2
    const ports = this.getInPorts()
    const usedPorts = this.getUsedInPorts(graph)
    const newPorts = this.getNewInPorts(
      Math.max(minNumberOfPorts - usedPorts.length, 1),
    )

    if (
      ports.length === minNumberOfPorts &&
      ports.length - usedPorts.length > 0
    ) {
      // noop
    } else if (ports.length === usedPorts.length) {
      this.addPorts(newPorts)
    } else if (ports.length + 1 > usedPorts.length) {
      this.prop(
        ['ports', 'items'],
        this.getOutPorts().concat(usedPorts).concat(newPorts), {
          rewrite: true,
        },
      )
    }

    return this
  }
}
MyShape.config({
  attrs: {
    root: {
      magnet: false,
    },
    body: {
      fill: '#f5f5f5',
      stroke: '#d9d9d9',
      strokeWidth: 1,
    },
  },
  ports: {
    items: [{
      group: 'out',
    }, ],
    groups: {
      in: {
        position: {
          name: 'top',
        },
        attrs: {
          portBody: {
            magnet: 'passive',
            r: 6,
            stroke: '#ffa940',
            fill: '#fff',
            strokeWidth: 2,
          },
        },
      },
      out: {
        position: {
          name: 'bottom',
        },
        attrs: {
          portBody: {
            magnet: true,
            r: 6,
            fill: '#fff',
            stroke: '#3199FF',
            strokeWidth: 2,
          },
        },
      },
    },
  },
  portMarkup: [{
    tagName: 'circle',
    selector: 'portBody',
  }, ],
})

// 高亮
const magnetAvailabilityHighlighter = {
  name: 'stroke',
  args: {
    attrs: {
      fill: '#fff',
      stroke: '#47C769',
    },
  },
}
export default (node) => {
  const graph = new Graph({
    container: document.getElementById(node),
    width: 600,
    height: 600,
    background: {
      color: '#fffbe6', // 设置画布背景颜色
    },
    translating: {
      restrict(view) {
        let cell = view.cell
        if (cell.isNode()) {
          return {
            x: 0,
            y: 40,
            width: 600,
            height: 40
          }
        }
      }
    },
    autoResize: true,
    resizing: {
      enabled: (view) => {
        return true
      },
      restricted: true,
      maxHeight: 40,
      minHeight: 40
    },
    grid: {
      visible: true,
      size: 10,
      type: 'doubleMesh',
      args: [{
          color: '#eee', // 主网格线颜色
          thickness: 1, // 主网格线宽度
        },
        {
          color: '#ddd', // 次网格线颜色
          thickness: 1, // 次网格线宽度
          factor: 5, // 主次网格线间隔
        },
      ],
    },
    highlighting: {
      magnetAvailable: magnetAvailabilityHighlighter,
      magnetAdsorbed: {
        name: 'stroke',
        args: {
          attrs: {
            fill: '#fff',
            stroke: '#31d0c6',
          },
        },
      },
    },
    connecting: {
      snap: true,
      allowBlank: false,
      allowLoop: false,
      highlight: true,
      connector: 'rounded',
      connectionPoint: 'boundary',
      router: "manhattan",
      createEdge() {
        return new Shape.Edge({
          attrs: {
            line: {
              stroke: '#a0a0a0',
              strokeWidth: 1,
              targetMarker: {
                name: 'classic',
                size: 0,
              },

              // sourceMarker: {
              //   name: 'classic',
              //   size: 7,
              // },
            },
          },
        })
      },
      validateConnection(e) {
        console.log(e)
        // if (!targetMagnet) {
        //   return false
        // }
        // let cells = graph.toJSON().cells
        // let checkout = cells.some(item => {
        //   return item.source.cell == targetView.cell.id
        // })
        // console.log(checkout)
        // console.log(targetView.cell.id)
        // console.log(targetMagnet.getAttribute('port'))
        // console.log(targetMagnet.getAttribute('port'))
        // if (targetMagnet.getAttribute('port-group') !== 'in') {
        //   return false
        // }
        // if (sourceView == targetView) {
        //   return false
        // }


        // if (targetView) {
        //   const node = targetView.cell
        //   if (node instanceof MyShape) {
        //     const portId = targetMagnet.getAttribute('port')
        //     const usedInPorts = node.getUsedInPorts(graph)
        //     if (usedInPorts.find((port) => port && port.id === portId)) {
        //       return false
        //     }
        //   }
        // }

        return true
      },
    },
  })

  graph.addNode(
    new MyShape().resize(120, 40).position(200, 50).updateInPorts(graph),
  )

  graph.addNode(
    new MyShape().resize(120, 40).position(400, 50).updateInPorts(graph),
  )

  graph.addNode(
    new MyShape().resize(120, 40).position(300, 250).updateInPorts(graph),
  )

  function update(view) {
    const cell = view.cell
    if (cell instanceof MyShape) {
      cell.getInPorts().forEach((port) => {
        const portNode = view.findPortElem(port.id, 'portBody')
        view.unhighlight(portNode, {
          highlighter: magnetAvailabilityHighlighter,
        })
      })
      cell.updateInPorts(graph)
    }
  }

  // graph.on('edge:connected', ({
  //   previousView,
  //   currentView
  // }) => {
  //   console.log(graph.toJSON())

  //   if (previousView) {
  //     update(previousView)
  //   }
  //   if (currentView) {
  //     update(currentView)
  //   }
  // })

  graph.on('edge:removed', ({
    edge,
    options
  }) => {
    if (!options.ui) {
      return
    }

    const target = edge.getTargetCell()
    if (target instanceof MyShape) {
      target.updateInPorts(graph)
    }
  })

  graph.on('edge:mouseenter', ({
    edge
  }) => {
    edge.addTools([
      'source-arrowhead',
      'target-arrowhead',
      {
        name: 'button-remove',
        args: {
          distance: -30,
        },
      },
    ])
  })

  graph.on('edge:mouseleave', ({
    edge
  }) => {
    edge.removeTools()
  })
  // graph.on('node:click', e => {
  //   console.log(e);
  // })
  graph.on('line:click', e => {
    console.log(e);
  })
  graph.on('node:mouseenter', ({
    node
  }) => {
    node.addTools({
      name: 'button-remove',
      args: {
        x: '100%',
        y: 0,
        offset: {
          x: -10,
          y: 10
        }
      }
    });
    // node.addTools({
    //   name: 'button',
    //   args: {
    //     x: "100%",
    //     y: 0,
    //     offset: {
    //       x: 10,
    //       y: 10
    //     }
    //   }
    // });
  })
  graph.on('node:mouseleave', ({
    node
  }) => {
    node.removeTool("button-remove");
  })
  graph.on('edge:mouseleave', ({
    edge
  }) => {
    edge.removeTools()
  })
  return graph
}
